﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Threading;

namespace eBrain
{
    public partial class TestControlWindow : Form
    {
        ExperimentMainForm myExpWin;
        XmlNodeList TestList;
        XmlDocument TestSequence;

        Experiment[] ExperimentArray;

        public EyeTracker myET;

        string sDataPath, sLogPath, sXMLPath;
        string sFolderName;
        string sInputMode;

        Experiment.InputMode InputMode;

        //int roi_sel_size;
        //int ScanPeriodMs, SelectionTimeWindowMs, SelectionTimePerc;
        Label[] lblTestNameArray;

        Button[] btTrainingII, btTrial;

        CheckBox[] cbTestArray;

        int CurrentExperiment = -1;

        //int ScreenWidth, ScreenHeight;

        public Logger myLog;

        System.Timers.Timer SessionElapsedTimer = new System.Timers.Timer();
        DateTime SessionStart = DateTime.MinValue;
        DateTime ExperimentStartTime;
        bool bExperimentRunning = false;

        bool ExperimentPaused = false;


        public TestControlWindow()
        {
            try
            {

                InitializeComponent();

                LoadSequenceXML();

                myLog = new Logger("ExpParser.log", sLogPath);

                tbSession.Text = DateTime.Now.Year.ToString("0000") + "-" + DateTime.Now.Month.ToString("00") + DateTime.Now.Day.ToString("00");

                myExpWin = new ExperimentMainForm();//this, ScreenWidth, ScreenHeight);//, roi_sel_size, SelectionTimePerc, ScanPeriodMs);

                myExpWin.Show();
                this.BringToFront();

                LoadExperimentArray();

                if (InputMode == Experiment.InputMode.Eyetracker)
                {
                    myET = new EyeTracker(myLog);

                    //Provo ad aprire il collegamento con l'Eyetracking
                    if (myET.TestEyelinkConnection())// myExpWin.ET_OpenEyelinkConnection())
                    {
                        rbEyetrackingInput.Checked = true;
                        btTestCalibration.Visible = true;
                    }
                    else
                    {
                        rbEyetrackingInput.Enabled = false;
                        btTestCalibration.Visible = false;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("TestControlWindow error : " + ex.Message + " " + ex.Source);
            }
        }


        /// <summary>
        /// Carica la sequenza di test da effettuare
        /// </summary>
        private void LoadSequenceXML()
        {
            int delta_y, x0, x1, y0;//, x2;

            try
            {
                x0 = 50;
                x1 = 250;
                //x2 = 300;

                y0 = 50;

                TestSequence = new XmlDocument();
                //TestSequence.Load(@"D:\eBrain\XML_test_scripts\TestSequence.xml");
                TestSequence.Load(@"\eBrain\TestSequence.xml");

                //ScanPeriodMs = int.Parse(TestSequence.SelectSingleNode("Session/ScanPeriod").InnerText.ToString());
                //SelectionTimeWindowMs = int.Parse(TestSequence.SelectSingleNode("Session/SelectionTimeWindow").InnerText.ToString());
                //SelectionTimePerc = int.Parse(TestSequence.SelectSingleNode("Session/SelectionTimePerc").InnerText.ToString());
                sDataPath = TestSequence.SelectSingleNode("Session/DataPath").InnerText;
                sLogPath = TestSequence.SelectSingleNode("Session/LogPath").InnerText;
                sXMLPath = TestSequence.SelectSingleNode("Session/XMLPath").InnerText;

                sInputMode = TestSequence.SelectSingleNode("Session/InputMode").InnerText;
                //if (TestSequence.SelectSingleNode("Session/ScreenWidth").InnerText != "")
                //    ScreenWidth = int.Parse(TestSequence.SelectSingleNode("Session/ScreenWidth").InnerText);
                //else
                //    ScreenWidth = 0;

                //if (TestSequence.SelectSingleNode("Session/ScreenHeight").InnerText != "")
                //    ScreenHeight = int.Parse(TestSequence.SelectSingleNode("Session/ScreenHeight").InnerText);
                //else
                //    ScreenHeight = 0;

                switch (sInputMode)
                {
                    case "Mouse":
                        rbMouseInput.Checked = true;
                        InputMode = Experiment.InputMode.MouseEmulation;
                        break;

                    case "Eyetracking":
                        rbEyetrackingInput.Checked = true;
                        InputMode = Experiment.InputMode.Eyetracker;
                        break;

                    case "Touch":
                        rbTouchInput.Checked = true;
                        rbTouchInput.Enabled = true;
                        InputMode = Experiment.InputMode.Touch;
                        break;
                }

                //roi_sel_size = SelectionTimeWindowMs / ScanPeriodMs;

                TestList = TestSequence.SelectNodes("Session/Experiments/Experiment");

                lblTestNameArray = new Label[TestList.Count];
                cbTestArray = new CheckBox[TestList.Count];
                btTrainingII = new Button[TestList.Count];
                btTrial = new Button[TestList.Count];

                delta_y = (this.Height - y0) / (TestList.Count + 2);

                for (int k = 0; k < TestList.Count; k++)
                {
                    lblTestNameArray[k] = new Label();
                    lblTestNameArray[k].Parent = this;
                    lblTestNameArray[k].BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                    lblTestNameArray[k].Location = new System.Drawing.Point(x0, (k + 1) * delta_y + y0);
                    lblTestNameArray[k].Font = new System.Drawing.Font("Microsoft Sans Serif", 10.0F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    lblTestNameArray[k].TextAlign = ContentAlignment.MiddleCenter;
                    //TestName[k].AutoSize = true;
                    lblTestNameArray[k].Size = new System.Drawing.Size(180, 18);

                    lblTestNameArray[k].Visible = true;

                    XmlDocument TestXML = new XmlDocument();
                    TestXML.Load(sXMLPath + TestList[k].InnerText);

                    lblTestNameArray[k].Text = TestXML.SelectSingleNode("Experiment/Name").InnerText.ToString();

                    cbTestArray[k] = new CheckBox();
                    cbTestArray[k].Parent = this;
                    cbTestArray[k].Location = new System.Drawing.Point(x1, (k + 1) * delta_y + y0);
                    cbTestArray[k].Checked = true;
                    cbTestArray[k].Size = new System.Drawing.Size(20, 18);

                    btTrainingII[k] = new Button();

                    //btTrain[k] = new Button();
                    //btTrain[k].Parent = this;
                    //btTrain[k].Location = new System.Drawing.Point(x2, (k + 1) * delta_y + y0);
                    //btTrain[k].Size = new System.Drawing.Size(60, 20);
                    //btTrain[k].Text = "Train";
                    ////btTrain[k].Font = new System.Drawing.Font("Microsoft Sans Serif", 10.0F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    //btTrain[k].Visible = true;

                }
                this.Invalidate();
            }
            catch (Exception ex)
            {
                MessageBox.Show("LoadXML error : " + ex.Message + " " + ex.Source);
            }
        }

        public void LoadExperimentArray()
        {
            ExperimentArray = new Experiment[TestList.Count];

            for (int k = 0; k < TestList.Count; k++)
            {
                XmlDocument TestXML = new XmlDocument();
                TestXML.Load(sXMLPath + TestList[k].InnerText);


                switch (TestXML.SelectSingleNode("Experiment/Type").InnerText.ToString())
                {
                    case "Saccade":
                    case "Antisaccade":
                        ExperimentArray[k] = new Exp_Saccade(this, myExpWin);
                        break;

                    case "MultipleChoice":
                        ExperimentArray[k] = new Exp_MultipleChoice(this, myExpWin);
                        break;

                    case "SmoothPursuit":
                        ExperimentArray[k] = new Exp_SmoothPursuit(this, myExpWin);
                        break;

                    case "VisualSearch":
                        ExperimentArray[k] = new Exp_VisualSearch(this, myExpWin);
                        break;

                    case "CardGambling":
                        ExperimentArray[k] = new Exp_Gambling(this, myExpWin);
                        break;
                    case "Wisconsin":
                        ExperimentArray[k] = new Exp_Wisconsin(this, myExpWin);
                        break;
                }
            }
        }

        //public void UpdateParameters()
        //{
        //    tbTimerPeriod.Text = ScanPeriodMs.ToString();
        //    tbTimeWindow.Text = SelectionTimeWindowMs.ToString();
        //    tbTriggerTreshPerc.Text = SelectionTimePerc.ToString();
        //}

        public void ExperimentCompleted()
        {
            lblTestNameArray[CurrentExperiment].BackColor = Color.Green;
            cbTestArray[CurrentExperiment].Checked = false;

            if (!myExpWin.bMultiMonitor)
                this.BringToFront();

            btStart.Enabled = true;
            btStop.Enabled = false;

            bExperimentRunning = false;
        }

        public void ExperimentStopped()
        {
            lblTestNameArray[CurrentExperiment].BackColor = Color.Yellow;
            //cbTestArray[CurrentExperiment].Checked = false;

            if (!myExpWin.bMultiMonitor)
                this.BringToFront();

            btStart.Enabled = true;
            btStop.Enabled = false;

            bExperimentRunning = false;
        }

        private void btExit_Click(object sender, EventArgs e)
        {
            //TODO: scaricare i dati relativi alla sessione
            if (InputMode == Experiment.InputMode.Eyetracker)
            {
                if (myET.IsConnected())
                    myET.Close();
            }
            //Experiment.CloseEyetrackerConnection();
            SessionElapsedTimer.Stop();

            Thread.Sleep(200);

            this.Close();
        }

        private void btStart_Click(object sender, EventArgs e)
        {

            if (tbSubjectID.Text != "")
            {

                sFolderName = sDataPath + tbSession.Text.Replace(" ", "") + "-" + (tbSubjectID.Text.Replace(" ", ""));

                //Creo la directory corrispondente
                if (!Directory.Exists(sFolderName))
                    Directory.CreateDirectory(sFolderName);
                ExperimentStartTime = DateTime.Now;

                //verifico quale sia l'esperimento della lista da fare partire
                int ExperimentNumber = -1;
                for (int k = 0; k < TestList.Count; k++)
                {
                    if (cbTestArray[k].Checked)
                    {
                        ExperimentNumber = k;
                        break;
                    }
                }

                if (ExperimentNumber >= 0)
                {
                    //faccio partire il timer della sessione
                    SessionElapsedTimer.Elapsed += new System.Timers.ElapsedEventHandler(SessionTimeElaspedEvent);
                    SessionElapsedTimer.Interval = 1000;
                    if (SessionStart == DateTime.MinValue)
                        SessionStart = DateTime.Now;

                    SessionElapsedTimer.Start();

                    CurrentExperiment = ExperimentNumber;

                    if (!myExpWin.bMultiMonitor)
                        myExpWin.BringToFront();
                    bExperimentRunning = true;

                    btStop.Enabled = true;
                    btStart.Enabled = false;

                    //aggiorno gli ultimi parametri della finestra di esecuzione degli esperimenti    
                    ExperimentArray[ExperimentNumber].SetDataPath(sFolderName.Replace(" ", ""));
                    ExperimentArray[ExperimentNumber].SetSubjectID(tbSubjectID.Text.Replace(" ", ""));
                    ExperimentArray[ExperimentNumber].SetInputMode(InputMode);

                    btPause.Enabled = true;

                    ExperimentArray[ExperimentNumber].StartExperiment(sXMLPath + TestList[ExperimentNumber].InnerText, cbSoundOn.Checked, cbCountdownOn.Checked);
                    //myExpWin.StartExperiment(sXMLPath + TestList[ExperimentNumber].InnerText, ScanPeriodMs, SelectionTimeWindowMs, SelectionTimePerc, cbSoundOn.Checked);
                }
            }
            else
            {
                MessageBox.Show("Sorry, Subject ID missing!");
            }

        }

        public void PromptToStartTrials(bool bTrainingAvailable)
        {

            if (bTrainingAvailable)
            {
                btDoTraining.Visible = true;
                btDoTraining.Enabled = true;
            }
            else
            {
                btDoTraining.Visible = false;
                //btDoTraining.Enabled = true;
            }

                btDoTrial.Visible = true;
                btDoTrial.Enabled = true;

            
            //DialogResult ret = MessageBox.Show("Press OK to start");
            //ExperimentArray[CurrentExperiment].StartTrials();
        }

        //public bool PromptToStartTrainingOrTrials()
        //{
        //    DialogResult ret = MessageBox.Show("Press Yes to start Trials, NO to redo Trainings", "", MessageBoxButtons.YesNo);

        //    return (ret == System.Windows.Forms.DialogResult.No);
        //}


        private void SessionTimeElaspedEvent(object sender, EventArgs e)
        {
            TimeSpan ts1, ts2;
            ts1 = DateTime.Now - SessionStart;
            ts2 = DateTime.Now - ExperimentStartTime;


            //lblSessionTime.Text = ts1.Hours.ToString("00") + ":" + ts1.Minutes.ToString("00") + ":" + ts1.Seconds.ToString("00");
            //if (bExperimentRunning)
            //    lblExperimentTime.Text = ts2.Hours.ToString("00") + ":" + ts2.Minutes.ToString("00") + ":" + ts2.Seconds.ToString("00");

            this.Invoke(new EventHandler(delegate
                {
                    lblSessionTime.Text = ts1.Hours.ToString("00") + ":" + ts1.Minutes.ToString("00") + ":" + ts1.Seconds.ToString("00");
                    if (bExperimentRunning)
                        lblExperimentTime.Text = ts2.Hours.ToString("00") + ":" + ts2.Minutes.ToString("00") + ":" + ts2.Seconds.ToString("00");
                }));
        }

        private void btStop_Click(object sender, EventArgs e)
        {
            SessionElapsedTimer.Stop();
            SessionElapsedTimer.Elapsed -= SessionTimeElaspedEvent;
            //myExpWin.StopExperiment();
            ExperimentArray[CurrentExperiment].StopExperiment();
            btStop.Enabled = false;
            btStart.Enabled = true;
            btPause.Enabled = false;


            btDoTrial.Visible = false;
            btDoTraining.Visible = false; 

        }

        ////Aggiorno i dati relativi ai parametri temporali, nel caso siano da cambiare
        //private void tbTimerPeriod_TextChanged(object sender, EventArgs e)
        //{
        //    ScanPeriodMs = int.Parse(tbTimerPeriod.Text);
        //}

        //private void tbTimeWindow_TextChanged(object sender, EventArgs e)
        //{
        //    SelectionTimeWindowMs = int.Parse(tbTimeWindow.Text);
        //}

        //private void tbTriggerTreshPerc_TextChanged(object sender, EventArgs e)
        //{
        //    SelectionTimePerc = int.Parse(tbTriggerTreshPerc.Text);
        //}

        private void btTestCalibration_Click(object sender, EventArgs e)
        {
            //myExpWin.ET_TestEyelinkCalibration();
            //ExperimentArray[CurrentExperiment].ET.TestEyelinkCalibration(;
        }

        private void rbEyetrackingInput_CheckedChanged(object sender, EventArgs e)
        {
            InputMode = Experiment.InputMode.Eyetracker;
 
            try
            {
           if (myET == null)
                myET = new EyeTracker(myLog);


                //Provo ad aprire il collegamento con l'Eyetracking
                if (myET.TestEyelinkConnection())// myExpWin.ET_OpenEyelinkConnection())
                {
                    rbEyetrackingInput.Checked = true;
                    btTestCalibration.Visible = true;
                }
                else
                {
                    rbEyetrackingInput.Enabled = false;
                    btTestCalibration.Visible = false;
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("TestControlWindow error : " + ex.Message + " " + ex.Source);
            }
        }


        private void rbMouseInput_CheckedChanged(object sender, EventArgs e)
        {
            InputMode = Experiment.InputMode.MouseEmulation;
        }

        public void updateTrialsNumbers(int act_num, int overall)
        {
            lblActTrialNum.Text = act_num.ToString();
            lblTotalTrialNum.Text  = overall.ToString();
        }

        public void updateTrialFigures(int score, int num_timeout)
        {
            lblScore.Text = score.ToString();
            lblNumOfTimeout.Text = num_timeout.ToString();
        }

        //private void btRunTrials_Click(object sender, EventArgs e)
        //{
        //    btRunTrials.Visible = false;
        //    this.Invoke(new EventHandler(delegate
        //    {
        //        ExperimentArray[CurrentExperiment].StartTrials();
        //        //myExpWin.StartTrials();
        //    }));
        //}

        private void TestControlWindow_Load(object sender, EventArgs e)
        {

        }

        private void TestControlWindow_KeyPress(object sender, KeyPressEventArgs e)
        {

        }

        private void btContinue_Click(object sender, EventArgs e)
        {
            
        }

        private void openSessionToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void openSingleTestToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void anonymousIDToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (anonymousIDToolStripMenuItem.Checked)
            {
                anonymousIDToolStripMenuItem.Checked = false;
                tbSubjectID.Enabled = true; 
            }
            else
            {
                anonymousIDToolStripMenuItem.Checked = true;
                tbSubjectID.Enabled = false; 
            }
        }

        private void btDoTraining_Click(object sender, EventArgs e)
        {
            btDoTraining.Enabled = false;
            btDoTrial.Enabled = false;
            ExperimentArray[CurrentExperiment].StartTrials(true);
        }

        private void btDoTrial_Click(object sender, EventArgs e)
        {
            btDoTrial.Enabled = false;
            btDoTraining.Enabled = false;
            ExperimentArray[CurrentExperiment].StartTrials(false);
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void btPause_Click(object sender, EventArgs e)
        {
            if (ExperimentPaused)
            {
                ExperimentArray[CurrentExperiment].UnPause();
                btPause.Text = "PAUSE";
                ExperimentPaused = false;
                btPause.BackColor = Color.MediumAquamarine;
            }
            else
            {
                ExperimentArray[CurrentExperiment].Pause();
                btPause.Text = "RESUME";
                ExperimentPaused = true;
                btPause.BackColor = Color.Yellow;
            }
        }
   
    }
}
